#ifndef CKKS_SRC_TEST_SCHEME_H_
#define CKKS_SRC_TEST_SCHEME_H_

#include "numb.h"
#include "context.h"
#include "secret_key.h"
#include "scheme.h"
#include "evaluator_utils.h"
#include "string_utils.h"
#include "time_utils.h"
#include "bootstrapping/homomorphic_mod.h"
#include "bootstrapping/bootstrapping.h"
#include "bootstrapping/cosine_approx.h"
#include "bootstrapping/homomorphic_encoding.h"

#include <vector>
#include <chrono>

using namespace std;

class TestScheme {
public:
    // 普通构造函数
    TestScheme() = default;

    TestScheme(const TestScheme &other) = delete;
    TestScheme &operator = (const TestScheme &other) = delete;
    TestScheme(TestScheme &&other) = delete;
    TestScheme &operator = (TestScheme &&other) = delete;

    static void TestEncodeSingle();

    static void TestEncodeBatch(long logN, long L, long K, long logp, long T, int gamma, long logSlots);

    static void TestEncryptSingle(long logN, long L, long logp);

    static void TestEncrypt(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestBasic(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestBaseConvert(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestBasePQ2T(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestBaseT2PQ(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestMultCt(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestMultPt(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestAddPt(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestAddCt(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestMultRepeat(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestSquare(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestMult(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestConjugateBatch(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestimultBatch();

    static void TestNegMult();

    static void TestRotateByPo2Batch(long logN, long L, long K, long T, long logp, int gamma, long logRotSlots,
                                     long logSlots, bool isLeft);

    static void TestRotateTime(long logN, long L, long K, long T, long logp, int gamma, long rotSlots, long logSlots,
                                bool isLeft);

    static void TestRotate(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestModDownToQ0AndEqual(long logN, long L, long logp, long logSlots);

    static void TestModUpToQ(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestCtS(long logp);

    static void TestEvalMod(long logN, long L, long K, long T, long logp, int gamma);

    static void TestBootstrapping(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestFHEMod(long logN, long L, long K, long T, long logp, int gamma, long logSlots);

    static void TestMultConst();
};

#endif
